#include <stdio.h>
#include "log.h"
#include "ql_type.h"
#include "account.h"
#include "largefile.h"
// -----------------------
// unix system
// -----------------------
#include <sys/time.h>
#include <time.h>

void print_log_func(char *content){
    printf("%s",content);
}

void print_log_time(char * time_buf, int size){
#if (defined(__unix)) || (defined(_WIN32) || defined(_WIN64))
    time_t t = time(NULL);
    struct tm* tp = localtime(&t);
    time_buf[strftime(time_buf, size, "%H:%M:%S", tp)] = '\0';
#else
    time_buf[0] = '\0';
#endif
}

OhErrType native_get_time(OhInt64Type *dst) {
    struct timeval t;
    gettimeofday(&t,NULL);
    *dst = (OhInt64Type)t.tv_sec * 1000000000 + (OhInt64Type)t.tv_usec*1000; // ns
    return ACCOUNT_SUCCESS;
}

int test_sign(){
    struct timeval start, end;

//    OhByteType acc_json[] = "{\"version\":\"4.0\",\"algo\":\"0x03\",\"privateKey\":\"0202020101010101010101010101010101010101010101010101010101010101\",\"publicKey\":\"04c542b416ff48d81be1651f25548c06d191cfa30cb81af51911830cf2e012cc9ff7fd76ddd1594c607160a97904331519240063916d8f361def5389730ac2d744\",\"address\":\"469339bdf3d3621bebea36c308de77939424e34e\"}";
    OhByteType acc_json[] = "{\"address\":\"8399b2b7e104cebb8b8938a2c79e26cb4733b0b5\",\"algo\":\"0x03\",\"version\":\"4.0\",\"publicKey\":\"049c660da3c16fd0df820b747d82344916db69d7553d2456323c820f1b1f4f225986d1f16cde06d99d94aa8998f0a14b6aeca21d7cad7670516cc911e4b035f9e5\",\"privateKey\":\"8747be107feb7959f4e8c8936a31aac5ffd4ed4d62d0e9edee2854531e62ea5e\"}";
    log_debug("----account test----");
    //create account
    AccountType my_account;
    OhErrType res = AccountInitJson(&my_account, acc_json);
    if(res != ACCOUNT_SUCCESS) {
        log_error("account_new failed : %d", res);
        return res;
    }
    // create tx
    gettimeofday(&start,NULL);
    TxType tx;
    OhByteType ex[] = "{\"id\":\"0F384\",\"name\":\"tom\",\"class\":\"0808\"}";
    res = TxSendNew(&tx, &my_account, my_account.addr, 0, ex, (OhByteType *)"[\"12345\",\"54321\"]");
    if(res != ACCOUNT_SUCCESS) {
        log_error("TxSendNew failed : %d", res);
        return res;
    }
    log_debug("=================================================================================");
    OhByteType out[1024];
    res = TxPrint(&tx, ADD_CURL_BODY,TX_TYPE_SENDTRANSACTION, out, 1024);
    if(res != ACCOUNT_SUCCESS) {
        log_error("TxSendNew failed : %d", res);
        return res;
    }
    log_info("%s",out);
    log_debug("=======COPY==THE==ABOVE==COMMAND==TO==THE==COMMAND==LINE==AND==EXECUTE==IT=======");
    gettimeofday(&end,NULL);
    log_debug("demo run time is %ldus",(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec));

    return 0;
}

int test_largefile(){
    // create account
    OhByteType priKey[] = "-----BEGIN EC PRIVATE KEY-----\n"
                         "MHQCAQEEIAICAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBoAcGBSuBBAAK\n"
                         "oUQDQgAExUK0Fv9I2BvhZR8lVIwG0ZHPowy4GvUZEYMM8uASzJ/3/Xbd0VlMYHFg\n"
                         "qXkEMxUZJABjkW2PNh3vU4lzCsLXRA==\n"
                         "-----END EC PRIVATE KEY-----";
    AccountType my_account;
    OhErrType res = AccountInitX509(&my_account, priKey);
    if(res != ACCOUNT_SUCCESS) {
        log_error("test_account_x509 failed : %d", res);
        return res;
    }
    // create large file
    LargefileType f;
    OhByteType* file_name = (OhByteType*)"../data.png";
    res = FileInfoNew(&f, file_name, (OhByteType*)"pic_upload_name.png", (OhByteType*)"des: test largefile", (OhByteType*)"", (OhByteType*)"");
    if(res != FILE_SUCCESS){
        log_error("test_largefile failed : %d", res);
        FileInfoFree(&f);
        return res;
    }
    res = FileCalMd5(&f);
    if(res != FILE_SUCCESS){
        log_error("test_largefile failed : %d", res);
        FileInfoFree(&f);
        return res;
    }
    OhByteType buf[400];
    res = FileInfoFormat(&f, buf, 400);
    if(res != FILE_SUCCESS){
        log_error("test_largefile failed : %d", res);
        FileInfoFree(&f);
        return res;
    }
    OhByteType hash[35];
    res = FileGetHash(&f, hash, 35);
    if(res != FILE_SUCCESS) {
        log_error("TxSendNew failed : %d", res);
        FileInfoFree(&f);
        return res;
    }
    FileInfoFree(&f);
    // create extraid
    OhByteType extraid[100];
    memset(extraid,0,sizeof(extraid));
    strcat((char*)extraid, "[");
    strcat((char*)extraid, (char*)hash);        // add hash
    strcat((char*)extraid, ",");
    strcat((char*)extraid, (char*)"\"13579\""); // add other extraid
    strcat((char*)extraid, "]");
    // create tx
    TxType tx;
    res = TxSendNew(&tx, &my_account, my_account.addr, 0, buf, extraid);
    if(res != ACCOUNT_SUCCESS) {
        log_error("TxSendNew failed : %d", res);
        return res;
    }
    OhByteType out[1100];
    log_debug("=============================== UPLOAD FILE =====================================");
    memset(out, 0, sizeof(out));
    res = TxPrint(&tx, ORIGIN_MSG,TX_TYPE_UPLOAD, out, 1100);
    if(res != ACCOUNT_SUCCESS) {
        log_error("TxSendNew failed : %d", res);
        return res;
    }
    log_info("curl -H 'type: upload' -H 'params: %s' --data-binary @%s -H \"Content-Type: application/octet-stream\" -H \"Expect: \" 8.136.20.47:8081",out,file_name);
    log_debug("============================== DOWNLOAD FILE =====================================");
    memset(out, 0, sizeof(out));
    res = TxPrint(&tx, ORIGIN_MSG,TX_TYPE_DOWNLOAD, out, 1100);
    if(res != ACCOUNT_SUCCESS) {
        log_error("TxSendNew failed : %d", res);
        return res;
    }
    log_info("curl -H 'type: download' -H 'params: %s' 8.136.20.47:8081 -o download.png",out);
    log_debug("=================================================================================");
    return 0;
}

int main(){

    SetPrintLogCallback(print_log_func);
    SetGetTimeCallback(print_log_time);
    LogSetQuiet(LOG_QUIET_FALSE);
    LogSetLevel(LOG_DEBUG);
    AccountSetTimeFunc(native_get_time);

    test_sign();
    test_largefile();

    return 0;
}